home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / UGPRG.ZIP / DENTHOR / TUT21.DOC < prev    next >
Encoding:
Text File  |  1996-07-27  |  44.3 KB  |  1,707 lines

  1.                    ╒═══════════════════════════════╕
  2.                    │         W E L C O M E         │
  3.                    │  To the VGA Trainer Program   │ │
  4.                    │              By               │ │
  5.                    │      DENTHOR of ASPHYXIA      │ │ │
  6.                    ╘═══════════════════════════════╛ │ │
  7.                      ────────────────────────────────┘ │
  8.                        ────────────────────────────────┘
  9.  
  10.                            --==[ PART 21 ]==--
  11.  
  12.  
  13.  
  14. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  15. ■ Introduction
  16.  
  17. Hi there! It's been quite a long time (again) since the last tutorial ...
  18. I'll bet some of you had given up one me ;-)
  19.  
  20. Today is my 21st birthday, so I decided it would be the perfect time to
  21. finish up this trainer which I have been meaning to send out for weeks.
  22. It's on texure mapping. I know, I know, I said light sourcing, then gourad,
  23. then texture mapping, but I got enough mail (a deluge in fact ;) telling me
  24. to do texure mapping...
  25.  
  26. I'll be using the code from Tut 20 quite extensively, so make sure you know
  27. whats going on in there... well, on with the show!
  28.  
  29. BTW, I've improved my web page quite a bit... give it a visit, I want to
  30. really ramp up that hit count :)
  31.  
  32. If you would like to contact me, or the team, there are many ways you
  33. can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
  34.                   on the ASPHYXIA BBS.
  35.             2) Write to :  Grant Smith
  36.                            P.O.Box 270 Kloof
  37.                            3640
  38.                            Natal
  39.                            South Africa
  40.             3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
  41.                   call during work hours). Call +27-31-73-2129 if you call
  42.                   from outside South Africa. (It's YOUR phone bill ;-))
  43.             4) Write to denthor@goth.vironix.co.za in E-Mail.
  44.             5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
  45.                us at once.
  46.  
  47. http://www.vironix.co.za/~grants                       (WWW)
  48. ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor       (FTP)
  49.  
  50.  
  51. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  52. ■  Free Direction Texture Mapping
  53.  
  54. There are two things you should know before we begin.
  55.  
  56. Firstly, I am cheating. The texture mapping I am going to show you is not
  57. perspective-correct, with clever divides for z-placement etc. This method
  58. looks almost as good and is quite a bit faster too.
  59.  
  60. Secondly, you will find it all rather easy. The reason for this is that it's
  61. all rather simple. I first made the routine by sitting down with some paper
  62. and a pencil and had it on the machine in a few hours. A while later when
  63. people on the net started discussing their methods, they were remarkably
  64. similar.
  65.  
  66. Let me show you what I mean.
  67.  
  68. Let us assume you have a texture of 128x128 (a straight array of bytes
  69. [0..127, 0..127]) which you want to map onto the side of a polygon. The
  70. problem of course being that the polygon can be all over the place, with
  71. one side longer then the other etc.
  72.  
  73. Our first step is to make sure we know which end is up... let me
  74. demonstrate...
  75.                       1
  76.                     +
  77.                  /    \
  78.               /         \
  79.           4 +            +  2
  80.               \        /
  81.                 \   /
  82.                   +
  83.                   3
  84.  
  85. Let us say that the above is the chosen polygon. We have decided that point
  86. 1 is the top left, point 3 is bottom right. This means that
  87.   1 - 2   is the top of the texture
  88.   2 - 3   is the right of the texture
  89.   3 - 4   is the bottom of the texture
  90.   4 - 1   is the left of the texture
  91.  
  92. The same polygon, but rotated :
  93.  
  94.                       3
  95.                     +
  96.                  /    \
  97.               /         \
  98.           2 +            +  4
  99.               \        /
  100.                 \   /
  101.                   +
  102.                   1
  103.  
  104. Although the positions of the points are different, point 1 is still the
  105. top left of our texture.
  106.  
  107.  
  108. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  109. ■  How to put it to screen
  110.  
  111. Okay, so now you have four points and know which one of them is also the top
  112. left of our texture. What next?
  113.  
  114. If you think back to our tutorial on polygons, you will remember we draw it
  115. scanline by scanline. We do texture mapping the same way.
  116.  
  117. Lets look at that picture again :
  118.  
  119.                       1
  120.                     +
  121.                a /    \  b
  122.               /         \
  123.           4 +            +  2
  124.               \        /
  125.                 \   /
  126.                   +
  127.                   3
  128.  
  129. We know that point 1 is at [0,0] in our texture. Point 2 is at [127,0],
  130. Point 3 is at [127,127], and Point 4 is at [0,127].
  131.  
  132. The clever bit, and the entire key to texture mapping, is making the
  133. logical leap that precisely half way between Point 1 and Point 2 (b), we are at
  134. [64,0] in our texture. (a) is in the same manner at [0,64].
  135.  
  136. That's it. All we need to know per y scanline is :
  137. The starting position on the x axis of the polgon line
  138. The position on the x in the texture map referenced by that point
  139. The position on the y in the texture map referenced by that point
  140.  
  141. The ending position on the x axis of the polgon line
  142. The position on the x in the texture map referenced by that point
  143. The position on the y in the texture map referenced by that point
  144.  
  145. Let me give you an example. Let's sat that (a) and (b) from the above
  146. picture are on the same y scanline. We know that the x of that scanline is
  147. (say) 100 pixels at the start and 200 pixels at the end, making it's width
  148. 100 pixels.
  149.  
  150. We know that on the left hand side, the texture is at [0,64], and at the
  151. right hand side, the texture is at [64,0]. In 100 pixels we have to
  152. traverse our texture from [0,64] to [64,0].
  153.  
  154. Assume at the start we have figured out the starting and ending points in
  155. the texture
  156.   textureX = 0;
  157.   textureY = 64;
  158.   textureEndX = 64;
  159.   textureEndY = 0;
  160.  
  161.   dx := (TextureEndX-TextureX)/(maxx-minx);
  162.   dy := (TextureEndY-TextureY)/(maxx-minx);
  163.   for loop1 := minx to maxx do BEGIN
  164.     PutPixel (loop1, ypos, texture [textureX, textureY], VGA);
  165.     textureX = textureX + dx;
  166.     textureY = textureY + dy;
  167.   END;
  168.  
  169.  
  170. Do the above for all the scanlines, and you have a texture mapped polygon!
  171. It's that simple.
  172.  
  173. We find our beginning and ending positions in the usual fasion. We know
  174. that Point 1 is [0,0]. We know that Point 2 is [127,0]. We know the number
  175. of scanlines on the y axis between Point 1 and Point 2.
  176.  
  177.   textureDX = 127/abs (point2.y - point1.y)
  178.  
  179. We run though all the y scanlines, starting from [0,0] and adding the above
  180. formula to the X every time. When we hit the last scanline, we will be at
  181. point [127,0] in the texure.
  182.  
  183. Repeat for all four sides, and you have the six needed variables per
  184. scanline.
  185.  
  186.  
  187. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  188. ■  In closing
  189.  
  190. As you can see, texture mapping (this type at least) is quite easy, and
  191. produces quite a good result. You will however notice a bit of distortion
  192. if you bring the polygon too close. This can be fixed by a) Subdividing the
  193. polygon, so the one is made up of four or more smaller polygons. Much
  194. bigger, but works; b) Using more accurate fixed point; or c) Figuring out
  195. perspective correct texture mapping, mapping along constant-z lines etc.
  196.  
  197. When people write me, they often refer to my "tutes". This stems back to
  198. Mark Feldman calling them such in the PCGPE. I always though a "tute" was
  199. something you did with your car to gain someones attention. I dunno, maybe
  200. its an Australian thing ;-)
  201.  
  202. I have been coding almost exclusively in C/C++ for the past year or so.
  203. Sorry guys, thats all they will pay me for ;) Anyway, the trainers will
  204. continue to be in Pascal for ease of understanding by beginners, but if
  205. someone (*ahem* Snowman) doesn't start converting them to C soon, I will do
  206. it myself. He also corrected any mistakes I made while he was converting,
  207. so I'd prefer he did it (sort of a proofreader after release...)
  208.  
  209. Send me presents! It's my birthday!
  210.  
  211. Byeeeee.....
  212.   - Denthor
  213.       16-04-96
  214.  
  215. Unit GFX3;
  216.  
  217.  
  218. INTERFACE
  219.  
  220. USES crt;
  221. CONST VGA = $A000;
  222.  
  223. TYPE Virtual = Array [1..64000] of byte;  { The size of our Virtual Screen }
  224.      VirtPtr = ^Virtual;                  { Pointer to the virtual screen }
  225.  
  226. VAR Virscr : VirtPtr;                     { Our first Virtual screen }
  227.     Vaddr  : word;                        { The segment of our virtual screen}
  228.     Scr_Ofs : Array[0..199] of Word;
  229.  
  230. Procedure SetMCGA;
  231.    { This procedure gets you into 320x200x256 mode. }
  232. Procedure SetText;
  233.    { This procedure returns you to text mode.  }
  234. Procedure Cls (Where:word;Col : Byte);
  235.    { This clears the screen to the specified color }
  236. Procedure SetUpVirtual;
  237.    { This sets up the memory needed for the virtual screen }
  238. Procedure ShutDown;
  239.    { This frees the memory used by the virtual screen }
  240. procedure flip(source,dest:Word);
  241.    { This copies the entire screen at "source" to destination }
  242. Procedure Pal(Col,R,G,B : Byte);
  243.    { This sets the Red, Green and Blue values of a certain color }
  244. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  245.   { This gets the Red, Green and Blue values of a certain color }
  246. procedure WaitRetrace;
  247.    {  This waits for a vertical retrace to reduce snow on the screen }
  248. Procedure Hline (x1,x2,y:word;col:byte;where:word);
  249.    { This draws a horizontal line from x1 to x2 on line y in color col }
  250. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  251.   { This draws a solid line from a,b to c,d in colour col }
  252. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  253.    { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  254.      in color col }
  255. Function rad (theta : real) : real;
  256.    {  This calculates the degrees of an angle }
  257. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
  258.    { This puts a pixel on the screen by writing directly to memory. }
  259. Function Getpixel (X,Y : Integer; where:word) :Byte;
  260.    { This gets the pixel on the screen by reading directly to memory. }
  261. Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  262.   { This loads the cel 'filename' into the pointer scrptr }
  263. Procedure LoadPal (FileName : string);
  264.   { This loads in an Autodesk Animator V1 pallette file }
  265.  
  266. IMPLEMENTATION
  267.  
  268. {──────────────────────────────────────────────────────────────────────────}
  269. Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  270. BEGIN
  271.   asm
  272.      mov        ax,0013h
  273.      int        10h
  274.   end;
  275. END;
  276.  
  277. {──────────────────────────────────────────────────────────────────────────}
  278. Procedure SetText;  { This procedure returns you to text mode.  }
  279. BEGIN
  280.   asm
  281.      mov        ax,0003h
  282.      int        10h
  283.   end;
  284. END;
  285.  
  286. {──────────────────────────────────────────────────────────────────────────}
  287. Procedure Cls (Where:word;Col : Byte); assembler;
  288.    { This clears the screen to the specified color }
  289. asm
  290.    push    es
  291.    mov     cx, 32000;
  292.    mov     es,[where]
  293.    xor     di,di
  294.    mov     al,[col]
  295.    mov     ah,al
  296.    rep     stosw
  297.    pop     es
  298. End;
  299.  
  300. {──────────────────────────────────────────────────────────────────────────}
  301. Procedure SetUpVirtual;
  302.    { This sets up the memory needed for the virtual screen }
  303. BEGIN
  304.   GetMem (VirScr,64000);
  305.   vaddr := seg (virscr^);
  306. END;
  307.  
  308. {──────────────────────────────────────────────────────────────────────────}
  309. Procedure ShutDown;
  310.    { This frees the memory used by the virtual screen }
  311. BEGIN
  312.   FreeMem (VirScr,64000);
  313. END;
  314.  
  315. {──────────────────────────────────────────────────────────────────────────}
  316. procedure flip(source,dest:Word); assembler;
  317.   { This copies the entire screen at "source" to destination }
  318. asm
  319.   push    ds
  320.   mov     ax, [Dest]
  321.   mov     es, ax
  322.   mov     ax, [Source]
  323.   mov     ds, ax
  324.   xor     si, si
  325.   xor     di, di
  326.   mov     cx, 32000
  327.   rep     movsw
  328.   pop     ds
  329. end;
  330.  
  331. {──────────────────────────────────────────────────────────────────────────}
  332. Procedure Pal(Col,R,G,B : Byte); assembler;
  333.   { This sets the Red, Green and Blue values of a certain color }
  334. asm
  335.    mov    dx,3c8h
  336.    mov    al,[col]
  337.    out    dx,al
  338.    inc    dx
  339.    mov    al,[r]
  340.    out    dx,al
  341.    mov    al,[g]
  342.    out    dx,al
  343.    mov    al,[b]
  344.    out    dx,al
  345. end;
  346.  
  347. {──────────────────────────────────────────────────────────────────────────}
  348. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  349.   { This gets the Red, Green and Blue values of a certain color }
  350. Var
  351.    rr,gg,bb : Byte;
  352. Begin
  353.    asm
  354.       mov    dx,3c7h
  355.       mov    al,col
  356.       out    dx,al
  357.  
  358.       add    dx,2
  359.  
  360.       in     al,dx
  361.       mov    [rr],al
  362.       in     al,dx
  363.       mov    [gg],al
  364.       in     al,dx
  365.       mov    [bb],al
  366.    end;
  367.    r := rr;
  368.    g := gg;
  369.    b := bb;
  370. end;
  371.  
  372. {──────────────────────────────────────────────────────────────────────────}
  373. procedure WaitRetrace; assembler;
  374.   {  This waits for a vertical retrace to reduce snow on the screen }
  375. label
  376.   l1, l2;
  377. asm
  378.     mov dx,3DAh
  379. l1:
  380.     in al,dx
  381.     and al,08h
  382.     jnz l1
  383. l2:
  384.     in al,dx
  385.     and al,08h
  386.     jz  l2
  387. end;
  388.  
  389. {──────────────────────────────────────────────────────────────────────────}
  390. Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
  391.   { This draws a horizontal line from x1 to x2 on line y in color col }
  392. asm
  393.   mov   ax,where
  394.   mov   es,ax
  395.   mov   ax,y
  396.   mov   di,ax
  397.   shl   ax,8
  398.   shl   di,6
  399.   add   di,ax
  400.   add   di,x1
  401.  
  402.   mov   al,col
  403.   mov   ah,al
  404.   mov   cx,x2
  405.   sub   cx,x1
  406.   shr   cx,1
  407.   jnc   @start
  408.   stosb
  409. @Start :
  410.   rep   stosw
  411. end;
  412.  
  413. {──────────────────────────────────────────────────────────────────────────}
  414. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  415.   { This draws a solid line from a,b to c,d in colour col }
  416.   function sgn(a:real):integer;
  417.   begin
  418.        if a>0 then sgn:=+1;
  419.        if a<0 then sgn:=-1;
  420.        if a=0 then sgn:=0;
  421.   end;
  422. var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
  423. begin
  424.      u:= c - a;
  425.      v:= d - b;
  426.      d1x:= SGN(u);
  427.      d1y:= SGN(v);
  428.      d2x:= SGN(u);
  429.      d2y:= 0;
  430.      m:= ABS(u);
  431.      n := ABS(v);
  432.      IF NOT (M>N) then
  433.      BEGIN
  434.           d2x := 0 ;
  435.           d2y := SGN(v);
  436.           m := ABS(v);
  437.           n := ABS(u);
  438.      END;
  439.      s := m shr 1;
  440.      FOR i := 0 TO m DO
  441.      BEGIN
  442.           putpixel(a,b,col,where);
  443.           s := s + n;
  444.           IF not (s<m) THEN
  445.           BEGIN
  446.                s := s - m;
  447.                a:= a + d1x;
  448.                b := b + d1y;
  449.           END
  450.           ELSE
  451.           BEGIN
  452.                a := a + d2x;
  453.                b := b + d2y;
  454.           END;
  455.      end;
  456. END;
  457.  
  458.  
  459. {──────────────────────────────────────────────────────────────────────────}
  460. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  461.   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  462.     in color col }
  463. var
  464.   x:integer;
  465.   mny,mxy:integer;
  466.   mnx,mxx,yc:integer;
  467.   mul1,div1,
  468.   mul2,div2,
  469.   mul3,div3,
  470.   mul4,div4:integer;
  471.  
  472. begin
  473.   mny:=y1; mxy:=y1;
  474.   if y2<mny then mny:=y2;
  475.   if y2>mxy then mxy:=y2;
  476.   if y3<mny then mny:=y3;
  477.   if y3>mxy then mxy:=y3;    { Choose the min y mny and max y mxy }
  478.   if y4<mny then mny:=y4;
  479.   if y4>mxy then mxy:=y4;
  480.  
  481.   if mny<0 then mny:=0;
  482.   if mxy>199 then mxy:=199;
  483.   if mny>199 then exit;
  484.   if mxy<0 then exit;        { Verticle range checking }
  485.  
  486.   mul1:=x1-x4; div1:=y1-y4;
  487.   mul2:=x2-x1; div2:=y2-y1;
  488.   mul3:=x3-x2; div3:=y3-y2;
  489.   mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }
  490.  
  491.   for yc:=mny to mxy do
  492.     begin
  493.       mnx:=320;
  494.       mxx:=-1;
  495.       if (y4>=yc) or (y1>=yc) then
  496.         if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }
  497.           if not(y4=y1) then
  498.             begin
  499.               x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
  500.               if x<mnx then
  501.                 mnx:=x;
  502.               if x>mxx then
  503.                 mxx:=x;       { Set point as start or end of horiz line }
  504.             end;
  505.       if (y1>=yc) or (y2>=yc) then
  506.         if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }
  507.           if not(y1=y2) then
  508.             begin
  509.               x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
  510.               if x<mnx then
  511.                 mnx:=x;
  512.               if x>mxx then
  513.                 mxx:=x;       { Set point as start or end of horiz line }
  514.             end;
  515.       if (y2>=yc) or (y3>=yc) then
  516.         if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }
  517.           if not(y2=y3) then
  518.             begin
  519.               x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
  520.               if x<mnx then
  521.                 mnx:=x;
  522.               if x>mxx then
  523.                 mxx:=x;       { Set point as start or end of horiz line }
  524.             end;
  525.       if (y3>=yc) or (y4>=yc) then
  526.         if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }
  527.           if not(y3=y4) then
  528.             begin
  529.               x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
  530.               if x<mnx then
  531.                 mnx:=x;
  532.               if x>mxx then
  533.                 mxx:=x;       { Set point as start or end of horiz line }
  534.             end;
  535.       if mnx<0 then
  536.         mnx:=0;
  537.       if mxx>319 then
  538.         mxx:=319;          { Range checking on horizontal line }
  539.       if mnx<=mxx then
  540.         hline (mnx,mxx,yc,color,where);   { Draw the horizontal line }
  541.     end;
  542.   end;
  543.  
  544. {──────────────────────────────────────────────────────────────────────────}
  545. Function rad (theta : real) : real;
  546.   {  This calculates the degrees of an angle }
  547. BEGIN
  548.   rad := theta * pi / 180
  549. END;
  550.  
  551. {──────────────────────────────────────────────────────────────────────────}
  552. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
  553.   { This puts a pixel on the screen by writing directly to memory. }
  554. asm
  555.    mov  ax,where
  556.    mov  es,ax
  557.    mov  bx,[y]
  558.    shl  bx,1
  559.    mov  di,word ptr [Scr_Ofs + bx]
  560.    add  di,[x]
  561.    mov  al,[col]
  562.    mov  es:[di],al
  563. end;
  564.  
  565.  
  566. {──────────────────────────────────────────────────────────────────────────}
  567. Function Getpixel (X,Y : Integer; where:word):byte; assembler;
  568.   { This puts a pixel on the screen by writing directly to memory. }
  569. asm
  570.    mov  ax,where
  571.    mov  es,ax
  572.    mov  bx,[y]
  573.    shl  bx,1
  574.    mov  di,word ptr [Scr_Ofs + bx]
  575.    add  di,[x]
  576.    mov  al,es:[di]
  577. end;
  578.  
  579. {──────────────────────────────────────────────────────────────────────────}
  580. Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  581.   { This loads the cel 'filename' into the pointer scrptr }
  582. var
  583.   Fil : file;
  584.   Buf : array [1..1024] of byte;
  585.   BlocksRead, Count : word;
  586. begin
  587.   assign (Fil, FileName);
  588.   reset (Fil, 1);
  589.   BlockRead (Fil, Buf, 800);    { Read and ignore the 800 byte header }
  590.   Count := 0;
  591.   BlocksRead := $FFFF;
  592.   while (not eof (Fil)) and (BlocksRead <> 0) do begin
  593.     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
  594.     Count := Count + 1024;
  595.   end;
  596.   close (Fil);
  597. end;
  598.  
  599.  
  600. procedure LoadPal (FileName : string);
  601. var
  602.   F:file;
  603.   loop1:integer;
  604.   pall:array[0..255,1..3] of byte;
  605. begin
  606.   assign (F, FileName);
  607.   reset (F,1);
  608.   blockread (F, pall,768);
  609.   close (F);
  610.   for loop1 := 0 to 255 do
  611.     Pal(loop1,pall[loop1,1],pall[loop1,2],pall[loop1,3]);
  612. end;
  613.  
  614.  
  615. VAR Loop1:integer;
  616.  
  617. BEGIN
  618.   For Loop1 := 0 to 199 do
  619.     Scr_Ofs[Loop1] := Loop1 * 320;
  620. END.{$X+}
  621. USES Crt,GFX3;
  622.  
  623. CONST VGA = $A000;
  624.       maxpolys = 18;
  625.  
  626.             A : Array [1..maxpolys,1..4,1..3] of integer =
  627.         (
  628.          ((-10, -10, 10 ),
  629.           (10 , -10, 10 ),
  630.           (10 , 10 , 10 ),
  631.           (-10, 10 , 10 )),
  632.  
  633.          ((-10, 10 , -10),
  634.           (10 , 10 , -10),
  635.           (10 , -10, -10),
  636.           (-10, -10, -10)),
  637.  
  638.          ((-10, 10 , 10 ),
  639.           (-10, 10 , -10),
  640.           (-10, -10, -10),
  641.           (-10, -10, 10 )),
  642.  
  643.          ((10 , -10, 10 ),
  644.           (10 , -10, -10),
  645.           (10 , 10 , -10),
  646.           (10 , 10 , 10 )),
  647.  
  648.          ((10 , 10 , 10 ),
  649.           (10 , 10 , -10),
  650.           (-10, 10 , -10),
  651.           (-10, 10 , 10 )),
  652.  
  653.          ((-10, -10, 10 ),
  654.           (-10, -10, -10),
  655.           (10 , -10, -10),
  656.           (10 , -10, 10 )),
  657.  
  658. (*********)
  659.  
  660.          ((-10, -10,-20 ),
  661.           (10 , -10,-20 ),
  662.           (10 , 10 ,-20 ),
  663.           (-10, 10 ,-20 )),
  664.  
  665.          ((-10, 10 , -30),
  666.           (10 , 10 , -30),
  667.           (10 , -10, -30),
  668.           (-10, -10, -30)),
  669.  
  670.          ((-10, 10 ,-20 ),
  671.           (-10, 10 , -30),
  672.           (-10, -10, -30),
  673.           (-10, -10,-20 )),
  674.  
  675.          ((10 , -10,-20 ),
  676.           (10 , -10, -30),
  677.           (10 , 10 , -30),
  678.           (10 , 10 ,-20 )),
  679.  
  680.          ((10 , 10 ,-20 ),
  681.           (10 , 10 , -30),
  682.           (-10, 10 , -30),
  683.           (-10, 10 ,-20 )),
  684.  
  685.          ((-10, -10,-20 ),
  686.           (-10, -10, -30),
  687.           (10 , -10, -30),
  688.           (10 , -10,-20 )),
  689.  
  690. (*********)
  691.  
  692.          ((-30, -10, 10 ),
  693.           (-20, -10, 10 ),
  694.           (-20, 10 , 10 ),
  695.           (-30, 10 , 10 )),
  696.  
  697.          ((-30, 10 , -10),
  698.           (-20, 10 , -10),
  699.           (-20, -10, -10),
  700.           (-30, -10, -10)),
  701.  
  702.          ((-30, 10 , 10 ),
  703.           (-30, 10 , -10),
  704.           (-30, -10, -10),
  705.           (-30, -10, 10 )),
  706.  
  707.          ((-20, -10, 10 ),
  708.           (-20, -10, -10),
  709.           (-20, 10 , -10),
  710.           (-20, 10 , 10 )),
  711.  
  712.          ((-20, 10 , 10 ),
  713.           (-20, 10 , -10),
  714.           (-30, 10 , -10),
  715.           (-30, 10 , 10 )),
  716.  
  717.          ((-30, -10, 10 ),
  718.           (-30, -10, -10),
  719.           (-20, -10, -10),
  720.           (-20, -10, 10 ))
  721.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  722.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  723.  
  724.       XOfs = 100;
  725.       YOfs = 160;
  726.  
  727.  
  728. Type Point = Record
  729.                x,y,z:integer;                { The data on every point we rotate}
  730.              END;
  731.  
  732.      Pictype = array [0..127,0..127] of byte;
  733.  
  734.  
  735. VAR Lines : Array [1..maxpolys,1..4] of Point; { The base object to be rotated }
  736.     Translated : Array [1..maxpolys,1..4] of Point; { The rotated object }
  737.     centre, tcentre : Array [1..maxpolys] of Point;
  738.     Order : Array[1..maxpolys] of integer;
  739.     lookup : Array [0..360,1..2] of integer; { Our sin and cos lookup table }
  740.     poly : array [0..199,1..2] of integer;
  741.     ytopclip,ybotclip:integer;  {where to clip our polys to}
  742.     xoff,yoff,zoff:integer;
  743.  
  744.     pic : ^pictype;
  745.     lefttable : array [-200..400,0..2] of integer;
  746.     righttable : array [-200..400,0..2] of integer;
  747.  
  748.  
  749. {──────────────────────────────────────────────────────────────────────────}
  750. Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  751. BEGIN
  752.   asm
  753.      mov        ax,0013h
  754.      int        10h
  755.   end;
  756. END;
  757.  
  758.  
  759. {──────────────────────────────────────────────────────────────────────────}
  760. Procedure Hline (x1,x2,y:integer;col:byte;where:word); assembler;
  761.   { This draws a horizontal line from x1 to x2 on line y in color col }
  762. asm
  763.   mov   ax,x1
  764.   cmp   ax,0
  765.   jge   @X1Okay
  766.   mov   x1,0
  767. @X1Okay :
  768.  
  769.   mov   ax,x2
  770.   cmp   ax,319
  771.   jle   @X2Okay
  772.   mov   x2,319
  773. @X2Okay :
  774.  
  775.   mov   ax,x1
  776.   cmp   ax,x2
  777.   jg    @Exit
  778.  
  779.   mov   ax,where
  780.   mov   es,ax
  781.   mov   ax,y
  782.   mov   di,ax
  783.   shl   ax,8
  784.   shl   di,6
  785.   add   di,ax
  786.   add   di,x1
  787.  
  788.   mov   al,col
  789.   mov   ah,al
  790.   mov   cx,x2
  791.   sub   cx,x1
  792.   shr   cx,1
  793.   jnc   @start
  794.   stosb
  795. @Start :
  796.   rep   stosw
  797. @Exit :
  798. end;
  799.  
  800.  
  801. {──────────────────────────────────────────────────────────────────────────}
  802. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  803.   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  804.     in color col }
  805. var miny,maxy:integer;
  806.     loop1:integer;
  807.  
  808. Procedure doside (x1,y1,x2,y2:integer);
  809.   { This scans the side of a polygon and updates the poly variable }
  810. VAR temp:integer;
  811.     x,xinc:integer;
  812.     loop1:integer;
  813. BEGIN
  814.   if y1=y2 then exit;
  815.   if y2<y1 then BEGIN
  816.     temp:=y2;
  817.     y2:=y1;
  818.     y1:=temp;
  819.     temp:=x2;
  820.     x2:=x1;
  821.     x1:=temp;
  822.   END;
  823.   xinc:=((x2-x1) shl 7) div (y2-y1);
  824.   x:=x1 shl 7;
  825.   for loop1:=y1 to y2 do BEGIN
  826.     if (loop1>(ytopclip)) and (loop1<(ybotclip)) then BEGIN
  827.       if (x shr 7<poly[loop1,1]) then poly[loop1,1]:=x shr 7;
  828.       if (x shr 7>poly[loop1,2]) then poly[loop1,2]:=x shr 7;
  829.     END;
  830.     x:=x+xinc;
  831.   END;
  832. END;
  833.  
  834. begin
  835.   asm
  836.     mov   si,offset poly
  837.     mov   cx,200
  838. @Loop1:
  839.     mov   ax,32766
  840.     mov   ds:[si],ax
  841.     inc   si
  842.     inc   si
  843.     mov   ax,-32767
  844.     mov   ds:[si],ax
  845.     inc   si
  846.     inc   si
  847.     loop  @loop1
  848.   end;     { Setting the minx and maxx values to extremes }
  849.   miny:=y1;
  850.   maxy:=y1;
  851.   if y2<miny then miny:=y2;
  852.   if y3<miny then miny:=y3;
  853.   if y4<miny then miny:=y4;
  854.   if y2>maxy then maxy:=y2;
  855.   if y3>maxy then maxy:=y3;
  856.   if y4>maxy then maxy:=y4;
  857.   if miny<ytopclip then miny:=ytopclip;
  858.   if maxy>ybotclip then maxy:=ybotclip;
  859.   if (miny>199) or (maxy<0) then exit;
  860.  
  861.   Doside (x1,y1,x2,y2);
  862.   Doside (x2,y2,x3,y3);
  863.   Doside (x3,y3,x4,y4);
  864.   Doside (x4,y4,x1,y1);
  865.  
  866.   for loop1:= miny to maxy do
  867.     hline (poly[loop1,1],poly[loop1,2],loop1,color,where);
  868. end;
  869.  
  870.  
  871. {──────────────────────────────────────────────────────────────────────────}
  872. Procedure SetUpPoints;
  873.   { This creates the lookup table }
  874. VAR loop1,loop2:integer;
  875. BEGIN
  876.   For loop1:=0 to 360 do BEGIN
  877.     lookup [loop1,1]:=round(sin (rad (loop1))*16384);
  878.     lookup [loop1,2]:=round(cos (rad (loop1))*16384);
  879.   END;
  880.   For loop1:=1 to maxpolys do BEGIN
  881.     centre[loop1].x := (lines[loop1,1].x + lines[loop1,2].x +
  882.                         lines[loop1,3].x + lines[loop1,4].x) div 4;
  883.     centre[loop1].y := (lines[loop1,1].y + lines[loop1,2].y +
  884.                         lines[loop1,3].y + lines[loop1,4].y) div 4;
  885.     centre[loop1].z := (lines[loop1,1].z + lines[loop1,2].z +
  886.                         lines[loop1,3].z + lines[loop1,4].z) div 4;
  887.   END;
  888. END;
  889.  
  890. Procedure LoadGFX;
  891.   { This loads up our texture }
  892. VAR f1 : File;
  893.     bob : array [0..255, 1..3] of byte;
  894.     loop1 : Integer;
  895. BEGIN
  896.   getmem (pic,sizeof(pic^));
  897.   loadcel ('side1.cel',pic);
  898.  
  899.   assign (f1, 'side1.cel');
  900.   reset (f1, 1);
  901.   seek (f1, 32);
  902.   blockread (f1, bob, 768);
  903.   close (f1);
  904.   for loop1:=0 to 255 do
  905.     Pal (loop1, bob[loop1,1], bob[loop1,2], bob[loop1,3]);
  906. END;
  907.  
  908.  
  909. {──────────────────────────────────────────────────────────────────────────}
  910. Procedure RotatePoints (x,Y,z:Integer);
  911.   { This rotates the objecct in lines to translated }
  912. VAR loop1,loop2:integer;
  913.     a,b,c:integer;
  914. BEGIN
  915.   For loop1:=1 to maxpolys do BEGIN
  916.     for loop2:=1 to 4 do BEGIN
  917.       b:=lookup[y,2];
  918.       c:=lines[loop1,loop2].x;
  919.       asm
  920.         mov   ax,b
  921.         imul  c
  922.         sal   ax,1
  923.         rcl   dx,1
  924.         sal   ax,1
  925.         rcl   dx,1
  926.         mov   a,dx
  927.       end;
  928.       b:=lookup[y,1];
  929.       c:=lines[loop1,loop2].z;
  930.       asm
  931.         mov   ax,b
  932.         imul  c
  933.         sal   ax,1
  934.         rcl   dx,1
  935.         sal   ax,1
  936.         rcl   dx,1
  937.         add   a,dx
  938.       end;
  939.       translated[loop1,loop2].x:=a;
  940.       translated[loop1,loop2].y:=lines[loop1,loop2].y;
  941.       b:=-lookup[y,1];
  942.       c:=lines[loop1,loop2].x;
  943.       asm
  944.         mov   ax,b
  945.         imul  c
  946.         sal   ax,1
  947.         rcl   dx,1
  948.         sal   ax,1
  949.         rcl   dx,1
  950.         mov   a,dx
  951.       end;
  952.       b:=lookup[y,2];
  953.       c:=lines[loop1,loop2].z;
  954.       asm
  955.         mov   ax,b
  956.         imul  c
  957.         sal   ax,1
  958.         rcl   dx,1
  959.         sal   ax,1
  960.         rcl   dx,1
  961.         add   a,dx
  962.       end;
  963.       translated[loop1,loop2].z:=a;
  964.  
  965.  
  966.       if x<>0 then BEGIN
  967.         b:=lookup[x,2];
  968.         c:=translated[loop1,loop2].y;
  969.         asm
  970.           mov   ax,b
  971.           imul  c
  972.           sal   ax,1
  973.           rcl   dx,1
  974.           sal   ax,1
  975.           rcl   dx,1
  976.           mov   a,dx
  977.         end;
  978.         b:=lookup[x,1];
  979.         c:=translated[loop1,loop2].z;
  980.         asm
  981.           mov   ax,b
  982.           imul  c
  983.           sal   ax,1
  984.           rcl   dx,1
  985.           sal   ax,1
  986.           rcl   dx,1
  987.           sub   a,dx
  988.         end;
  989.         b:=lookup[x,1];
  990.         c:=translated[loop1,loop2].y;
  991.         translated[loop1,loop2].y:=a;
  992.         asm
  993.           mov   ax,b
  994.           imul  c
  995.           sal   ax,1
  996.           rcl   dx,1
  997.           sal   ax,1
  998.           rcl   dx,1
  999.           mov   a,dx
  1000.         end;
  1001.         b:=lookup[x,2];
  1002.         c:=translated[loop1,loop2].z;
  1003.         asm
  1004.           mov   ax,b
  1005.           imul  c
  1006.           sal   ax,1
  1007.           rcl   dx,1
  1008.           sal   ax,1
  1009.           rcl   dx,1
  1010.           add   a,dx
  1011.         end;
  1012.         translated[loop1,loop2].z:=a;
  1013.       END;
  1014.  
  1015.  
  1016.  
  1017.  
  1018.       if z<>0 then BEGIN
  1019.         b:=lookup[z,2];
  1020.         c:=translated[loop1,loop2].x;
  1021.         asm
  1022.           mov   ax,b
  1023.           imul  c
  1024.           sal   ax,1
  1025.           rcl   dx,1
  1026.           sal   ax,1
  1027.           rcl   dx,1
  1028.           mov   a,dx
  1029.         end;
  1030.         b:=lookup[z,1];
  1031.         c:=translated[loop1,loop2].y;
  1032.         asm
  1033.           mov   ax,b
  1034.           imul  c
  1035.           sal   ax,1
  1036.           rcl   dx,1
  1037.           sal   ax,1
  1038.           rcl   dx,1
  1039.           sub   a,dx
  1040.         end;
  1041.         b:=lookup[z,1];
  1042.         c:=translated[loop1,loop2].x;
  1043.         translated[loop1,loop2].x:=a;
  1044.         asm
  1045.           mov   ax,b
  1046.           imul  c
  1047.           sal   ax,1
  1048.           rcl   dx,1
  1049.           sal   ax,1
  1050.           rcl   dx,1
  1051.           mov   a,dx
  1052.         end;
  1053.         b:=lookup[z,2];
  1054.         c:=translated[loop1,loop2].y;
  1055.         asm
  1056.           mov   ax,b
  1057.           imul  c
  1058.           sal   ax,1
  1059.           rcl   dx,1
  1060.           sal   ax,1
  1061.           rcl   dx,1
  1062.           add   a,dx
  1063.         end;
  1064.         translated[loop1,loop2].y:=a;
  1065.       END;
  1066.     END;
  1067.   END;
  1068.  
  1069.  
  1070. {******************}
  1071.   For loop1:=1 to maxpolys do BEGIN
  1072.     b:=lookup[y,2];
  1073.     c:=centre[loop1].x;
  1074.     asm
  1075.       mov   ax,b
  1076.       imul  c
  1077.       sal   ax,1
  1078.       rcl   dx,1
  1079.       sal   ax,1
  1080.       rcl   dx,1
  1081.       mov   a,dx
  1082.     end;
  1083.     b:=lookup[y,1];
  1084.     c:=centre[loop1].z;
  1085.     asm
  1086.       mov   ax,b
  1087.       imul  c
  1088.       sal   ax,1
  1089.       rcl   dx,1
  1090.       sal   ax,1
  1091.       rcl   dx,1
  1092.       add   a,dx
  1093.     end;
  1094.     tcentre[loop1].x:=a;
  1095.     tcentre[loop1].y:=centre[loop1].y;
  1096.     b:=-lookup[y,1];
  1097.     c:=centre[loop1].x;
  1098.     asm
  1099.       mov   ax,b
  1100.       imul  c
  1101.       sal   ax,1
  1102.       rcl   dx,1
  1103.       sal   ax,1
  1104.       rcl   dx,1
  1105.       mov   a,dx
  1106.     end;
  1107.     b:=lookup[y,2];
  1108.     c:=centre[loop1].z;
  1109.     asm
  1110.       mov   ax,b
  1111.       imul  c
  1112.       sal   ax,1
  1113.       rcl   dx,1
  1114.       sal   ax,1
  1115.       rcl   dx,1
  1116.       add   a,dx
  1117.     end;
  1118.     tcentre[loop1].z:=a;
  1119.  
  1120.  
  1121.     if x<>0 then BEGIN
  1122.       b:=lookup[x,2];
  1123.       c:=tcentre[loop1].y;
  1124.       asm
  1125.         mov   ax,b
  1126.         imul  c
  1127.         sal   ax,1
  1128.         rcl   dx,1
  1129.         sal   ax,1
  1130.         rcl   dx,1
  1131.         mov   a,dx
  1132.       end;
  1133.       b:=lookup[x,1];
  1134.       c:=tcentre[loop1].z;
  1135.       asm
  1136.         mov   ax,b
  1137.         imul  c
  1138.         sal   ax,1
  1139.         rcl   dx,1
  1140.         sal   ax,1
  1141.         rcl   dx,1
  1142.         sub   a,dx
  1143.       end;
  1144.       b:=lookup[x,1];
  1145.       c:=tcentre[loop1].y;
  1146.       tcentre[loop1].y:=a;
  1147.       asm
  1148.         mov   ax,b
  1149.         imul  c
  1150.         sal   ax,1
  1151.         rcl   dx,1
  1152.         sal   ax,1
  1153.         rcl   dx,1
  1154.         mov   a,dx
  1155.       end;
  1156.       b:=lookup[x,2];
  1157.       c:=tcentre[loop1].z;
  1158.       asm
  1159.         mov   ax,b
  1160.         imul  c
  1161.         sal   ax,1
  1162.         rcl   dx,1
  1163.         sal   ax,1
  1164.         rcl   dx,1
  1165.         add   a,dx
  1166.       end;
  1167.       tcentre[loop1].z:=a;
  1168.     END;
  1169.  
  1170.  
  1171.  
  1172.  
  1173.     if z<>0 then BEGIN
  1174.       b:=lookup[z,2];
  1175.       c:=tcentre[loop1].x;
  1176.       asm
  1177.         mov   ax,b
  1178.         imul  c
  1179.         sal   ax,1
  1180.         rcl   dx,1
  1181.         sal   ax,1
  1182.         rcl   dx,1
  1183.         mov   a,dx
  1184.       end;
  1185.       b:=lookup[z,1];
  1186.       c:=tcentre[loop1].y;
  1187.       asm
  1188.         mov   ax,b
  1189.         imul  c
  1190.         sal   ax,1
  1191.         rcl   dx,1
  1192.         sal   ax,1
  1193.         rcl   dx,1
  1194.         sub   a,dx
  1195.       end;
  1196.       b:=lookup[z,1];
  1197.       c:=tcentre[loop1].x;
  1198.       tcentre[loop1].x:=a;
  1199.       asm
  1200.         mov   ax,b
  1201.         imul  c
  1202.         sal   ax,1
  1203.         rcl   dx,1
  1204.         sal   ax,1
  1205.         rcl   dx,1
  1206.         mov   a,dx
  1207.       end;
  1208.       b:=lookup[z,2];
  1209.       c:=tcentre[loop1].y;
  1210.       asm
  1211.         mov   ax,b
  1212.         imul  c
  1213.         sal   ax,1
  1214.         rcl   dx,1
  1215.         sal   ax,1
  1216.         rcl   dx,1
  1217.         add   a,dx
  1218.       end;
  1219.       tcentre[loop1].y:=a;
  1220.     END;
  1221.   END;
  1222. END;
  1223.  
  1224.  
  1225. Procedure TextureMapPoly (x1,y1,x2,y2,x3,y3,x4,y4:integer;where:word);
  1226.   { The main procedure, contains various nested procedures }
  1227. VAR miny, maxy, loop1 : integer;
  1228.  
  1229. Procedure scanleftside (x1,x2,ytop,lineheight:integer;side:byte);
  1230.   { Scan in our needed variables ... X on the left, texturmap X, texturemap Y}
  1231. VAR x,px,py,xadd,pxadd,pyadd:integer;
  1232.     y:integer;
  1233. BEGIN
  1234.   lineheight:=lineheight+1;
  1235.   xadd:=(x2-x1) shl 7 div lineheight;
  1236.   if side = 1 then BEGIN
  1237.     px:=(127-1) shl 7;
  1238.     py:=0;
  1239.     pxadd:=(-127 shl 7) div lineheight;
  1240.     pyadd:=0;
  1241.   END;
  1242.   if side = 2 then BEGIN
  1243.     px:=127 shl 7;
  1244.     py:=127 shl 7;
  1245.     pxadd:=0;
  1246.     pyadd:=(-127 shl 7) div lineheight;
  1247.   END;
  1248.   if side = 3 then BEGIN
  1249.     px:=0;
  1250.     py:=127 shl 7;
  1251.     pxadd:=127 shl 7 div lineheight;
  1252.     pyadd:=0;
  1253.   END;
  1254.   if side = 4 then BEGIN
  1255.     px:=0;
  1256.     py:=0;
  1257.     pxadd:=0;
  1258.     pyadd:=127 shl 7 div lineheight;
  1259.   END;
  1260.   x:=x1 shl 7;
  1261.   for y:=0 to lineheight do BEGIN
  1262.     lefttable[ytop+y,0]:=x shr 7;
  1263.     lefttable[ytop+y,1]:=px shr 7;
  1264.     lefttable[ytop+y,2]:=py shr 7;
  1265.     x:=x+xadd;
  1266.     px:=px+pxadd;
  1267.     py:=py+pyadd;
  1268.   END;
  1269. END;
  1270.  
  1271. Procedure scanrightside (x1,x2,ytop,lineheight:integer;side:byte);
  1272.   { Scan in our needed variables ... X on the right, texturmap X, texturemap Y}
  1273. VAR x,px,py,xadd,pxadd,pyadd:integer;
  1274.     y:integer;
  1275. BEGIN
  1276.   lineheight:=lineheight+1;
  1277.   xadd:=(x2-x1) shl 7 div lineheight;
  1278.   if side = 1 then BEGIN
  1279.     px:=0;
  1280.     py:=0;
  1281.     pxadd:=127 shl 7 div lineheight;
  1282.     pyadd:=0;
  1283.   END;
  1284.   if side = 2 then BEGIN
  1285.     px:=127 shl 7;
  1286.     py:=0;
  1287.     pxadd:=0;
  1288.     pyadd:=127 shl 7 div lineheight;
  1289.   END;
  1290.   if side = 3 then BEGIN
  1291.     px:=127 shl 7;
  1292.     py:=127 shl 7;
  1293.     pxadd:=(-127) shl 7 div lineheight;
  1294.     pyadd:=0;
  1295.   END;
  1296.   if side = 4 then BEGIN
  1297.     px:=0;
  1298.     py:=127 shl 7;
  1299.     pxadd:=0;
  1300.     pyadd:=(-127) shl 7 div lineheight;
  1301.   END;
  1302.   x:=x1 shl 7;
  1303.   for y:=0 to lineheight do BEGIN
  1304.     righttable[ytop+y,0]:=x shr 7;
  1305.     righttable[ytop+y,1]:=px shr 7;
  1306.     righttable[ytop+y,2]:=py shr 7;
  1307.     x:=x+xadd;
  1308.     px:=px+pxadd;
  1309.     py:=py+pyadd;
  1310.   END;
  1311. END;
  1312.  
  1313.  
  1314. Procedure Texturemap;
  1315.   { This uses the tables we have created to actually draw the texture }
  1316. VAR px1,py1:integer;
  1317.     px2,py2:integer;
  1318.     polyx1,polyx2,y,linewidth:integer;
  1319.     pxadd,pyadd:integer;
  1320.     bob, twhere :word;
  1321. BEGIN
  1322.   bob:=seg (pic^);
  1323.   tWhere := Where;      { ds is used elsewhere ... variables are not accessable }
  1324.   if miny<0 then miny:=0;
  1325.   if maxy>199 then maxy:=199;
  1326.   if miny<ytopclip then miny:=ytopclip;
  1327.   if maxy>ybotclip then maxy:=ybotclip;
  1328.   if maxy-miny<2 then exit;
  1329.   if miny>199 then exit;
  1330.   if maxy<0 then exit;
  1331.   for y:=miny to maxy do BEGIN
  1332.     polyx1:=lefttable[y,0];      { X Starting position }
  1333.     px1:=lefttable[y,1] shl 7;   { Texture X at start  }
  1334.     py1:=lefttable[y,2] shl 7;   { Texture Y at stary  }
  1335.     polyx2:=righttable[y,0];     { X Ending position   }
  1336.     px2:=righttable[y,1] shl 7;  { Texture X at end    }
  1337.     py2:=righttable[y,2] shl 7;  { Texture Y at end    }
  1338.     linewidth:=polyx2-polyx1;    { Width of line }
  1339.     if linewidth<=0 then linewidth:=1;
  1340.     pxadd:=(px2-px1) div linewidth;
  1341.     pyadd:=(py2-py1) div linewidth;
  1342.       asm
  1343.         push    ds
  1344.         mov     bx,polyx1
  1345.         mov     di,bx
  1346.  
  1347.         mov     dx,[Y]
  1348.         mov     bx, dx
  1349.         shl     dx, 8
  1350.         shl     bx, 6
  1351.         add     dx, bx
  1352.         add     di, dx
  1353.         mov     ax,twhere        { es:di points to start of line }
  1354.         mov     es,ax
  1355.  
  1356.         mov     bx, px1
  1357.  
  1358.         mov     cx,lineWidth
  1359.         mov     dx, bob
  1360.         mov     ds, dx
  1361.  
  1362.         mov     dx,py1
  1363. @Loop1 :
  1364.         xor     si,si
  1365.         mov     ax,bx
  1366.         and     ax,1111111110000000b;   { Get rid of fixed point }
  1367.         add     si,ax
  1368.         mov     ax,dx
  1369.         shr     ax,7
  1370.         add     si,ax           { get the pixel in our texture }
  1371.         movsb                   { draw the pixel to the screen }
  1372.         mov     ax,pxadd
  1373.         add     bx,ax
  1374.         mov     ax,pyadd
  1375.         add     dx,ax           { increment our position in the texture }
  1376.         loop    @loop1
  1377.         pop     ds
  1378.       end;
  1379.   END;
  1380. END;
  1381.  
  1382. BEGIN
  1383.   miny:=32767;
  1384.   maxy:=0;
  1385.  
  1386.   if y1<miny then miny:=y1;
  1387.   if y1>maxy then maxy:=y1;
  1388.   if y2<miny then miny:=y2;
  1389.   if y2>maxy then maxy:=y2;
  1390.   if y3<miny then miny:=y3;
  1391.   if y3>maxy then maxy:=y3;
  1392.   if y4<miny then miny:=y4;
  1393.   if y4>maxy then maxy:=y4;
  1394.  
  1395.   if miny>maxy-5 then exit;     { Why paint slivers? }
  1396.  
  1397.   if (y2<y1) then
  1398.     scanleftside (x2,x1,y2,y1-y2,1)
  1399.   else
  1400.     scanrightside (x1,x2,y1,y2-y1,1);
  1401.   { If point2.y is above point1.y, Point1 to Point2 is on the "left",
  1402.     and our leftside array must be altered }
  1403.  
  1404.   if (y3<y2) then
  1405.     scanleftside (x3,x2,y3,y2-y3,2)
  1406.   else
  1407.     scanrightside (x2,x3,y2,y3-y2,2);
  1408.  
  1409.   if (y4<y3) then
  1410.     scanleftside (x4,x3,y4,y3-y4,3)
  1411.   else
  1412.     scanrightside (x3,x4,y3,y4-y3,3);
  1413.  
  1414.   if (y1<y4) then
  1415.     scanleftside (x1,x4,y1,y4-y1,4)
  1416.   else
  1417.     scanrightside (x4,x1,y4,y1-y4,4);
  1418.  
  1419.   texturemap;
  1420. END;
  1421.  
  1422.  
  1423.  
  1424. {──────────────────────────────────────────────────────────────────────────}
  1425. Procedure DrawPoints;
  1426.   { This draws the translated object to the virtual screen }
  1427. VAR loop1,loop2:Integer;
  1428.     temp, normal:integer;
  1429.     nx:integer;
  1430.     tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4:integer;
  1431. BEGIN
  1432.   For loop2:=1 to maxpolys do BEGIN
  1433.     loop1:=order[loop2];
  1434.     If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0)
  1435.        and (translated[loop1,3].z+zoff<0) and (translated[loop1,4].z+zoff<0)
  1436.        then BEGIN
  1437.       temp:=round (translated[loop1,1].z)+zoff;
  1438.       nx:=translated[loop1,1].X;
  1439.       asm
  1440.         mov   ax,nx
  1441.         mov   dx,ax
  1442.         sal   ax,8
  1443.         sar   dx,8
  1444.         idiv  temp
  1445.         add   ax,YOfs
  1446.         mov   nx,ax
  1447.       end;
  1448.       tx1:=nx;
  1449.       nx:=translated[loop1,1].Y;
  1450.       asm
  1451.         mov   ax,nx
  1452.         mov   dx,ax
  1453.         sal   ax,8
  1454.         sar   dx,8
  1455.         idiv  temp
  1456.         add   ax,XOfs
  1457.         mov   nx,ax
  1458.       end;
  1459.       ty1:=nx;
  1460.  
  1461.  
  1462.       temp:=round (translated[loop1,2].z)+zoff;
  1463.       nx:=translated[loop1,2].X;
  1464.       asm
  1465.         mov   ax,nx
  1466.         mov   dx,ax
  1467.         sal   ax,8
  1468.         sar   dx,8
  1469.         idiv  temp
  1470.         add   ax,YOfs
  1471.         mov   nx,ax
  1472.       end;
  1473.       tx2:=nx;
  1474.       nx:=translated[loop1,2].Y;
  1475.       asm
  1476.         mov   ax,nx
  1477.         mov   dx,ax
  1478.         sal   ax,8
  1479.         sar   dx,8
  1480.         idiv  temp
  1481.         add   ax,XOfs
  1482.         mov   nx,ax
  1483.       end;
  1484.       ty2:=nx;
  1485.  
  1486.  
  1487.       temp:=round (translated[loop1,3].z)+zoff;
  1488.       nx:=translated[loop1,3].X;
  1489.       asm
  1490.         mov   ax,nx
  1491.         mov   dx,ax
  1492.         sal   ax,8
  1493.         sar   dx,8
  1494.         idiv  temp
  1495.         add   ax,YOfs
  1496.         mov   nx,ax
  1497.       end;
  1498.       tx3:=nx;
  1499.       nx:=translated[loop1,3].Y;
  1500.       asm
  1501.         mov   ax,nx
  1502.         mov   dx,ax
  1503.         sal   ax,8
  1504.         sar   dx,8
  1505.         idiv  temp
  1506.         add   ax,XOfs
  1507.         mov   nx,ax
  1508.       end;
  1509.       ty3:=nx;
  1510.  
  1511.  
  1512.       temp:=round (translated[loop1,4].z)+zoff;
  1513.       nx:=translated[loop1,4].X;
  1514.       asm
  1515.         mov   ax,nx
  1516.         mov   dx,ax
  1517.         sal   ax,8
  1518.         sar   dx,8
  1519.         idiv  temp
  1520.         add   ax,YOfs
  1521.         mov   nx,ax
  1522.       end;
  1523.       tx4:=nx;
  1524.       nx:=translated[loop1,4].Y;
  1525.       asm
  1526.         mov   ax,nx
  1527.         mov   dx,ax
  1528.         sal   ax,8
  1529.         sar   dx,8
  1530.         idiv  temp
  1531.         add   ax,XOfs
  1532.         mov   nx,ax
  1533.       end;
  1534.       ty4:=nx;
  1535.  
  1536.       normal:=(ty1-ty3)*(tx2-tx1)-(tx1-tx3)*(ty2-ty1);
  1537.       if normal<0 then
  1538.         TextureMapPoly (tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4,vaddr);
  1539. {        drawpoly (tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4,loop1,vaddr);}
  1540.     END;
  1541.   END;
  1542. END;
  1543.  
  1544.  
  1545.  
  1546. {──────────────────────────────────────────────────────────────────────────}
  1547. Procedure SortPoints;
  1548. VAR loop1,curpos, temp:integer;
  1549. BEGIN
  1550.   for loop1:=1 to maxpolys do BEGIN
  1551.     order[loop1]:=loop1;
  1552.   END;
  1553.   curpos := 1;
  1554.   while curpos<maxpolys do BEGIN
  1555.     if tcentre[curpos].z > tcentre[curpos+1].z then BEGIN
  1556.       temp := tcentre[curpos+1].x;
  1557.       tcentre[curpos+1].x := tcentre[curpos].x;
  1558.       tcentre[curpos].x := temp;
  1559.  
  1560.       temp := tcentre[curpos+1].y;
  1561.       tcentre[curpos+1].y := tcentre[curpos].y;
  1562.       tcentre[curpos].y := temp;
  1563.  
  1564.       temp := tcentre[curpos+1].z;
  1565.       tcentre[curpos+1].z := tcentre[curpos].z;
  1566.       tcentre[curpos].z := temp;
  1567.  
  1568.       temp := order[curpos+1];
  1569.       order[curpos+1] := order[curpos];
  1570.       order[curpos] := temp;
  1571.  
  1572.       curpos:=0;
  1573.     END;
  1574.     curpos:=curpos+1;
  1575.   END;
  1576. END;
  1577.  
  1578.  
  1579. {──────────────────────────────────────────────────────────────────────────}
  1580. Procedure MoveAround;
  1581.   { This is the main display procedure. }
  1582. VAR deg,deg2,loop1,loop2:integer;
  1583.     ch:char;
  1584.  
  1585. BEGIN
  1586.   pal (1,  0, 0,63);
  1587.   pal (2,  0,32,63);
  1588.   pal (3, 32, 0,63);
  1589.   pal (4, 32,32,63);
  1590.   pal (5,  0,63,63);
  1591.   pal (6, 32,63,63);
  1592.  
  1593.   pal ( 7,  0,63, 0);
  1594.   pal ( 8,  0,63,32);
  1595.   pal ( 9, 32,63, 0);
  1596.   pal (10, 32,63,32);
  1597.   pal (11,  0,63,63);
  1598.   pal (12, 32,63,63);
  1599.  
  1600.   pal (13, 63, 0, 0);
  1601.   pal (14, 63,32, 0);
  1602.   pal (15, 63, 0,32);
  1603.   pal (16, 63,32,32);
  1604.   pal (17, 63,63, 0);
  1605.   pal (18, 63,63,32);
  1606. {  for loop1:=1 to 15 do
  1607.     pal (loop1,0,loop1*4+3,63-(loop1*4+3));}
  1608.   pal (100,50,50,50);
  1609.  
  1610.   deg:=0;
  1611.   deg2:=0;
  1612.   ch:=#0;
  1613.   Cls (vaddr,0);
  1614.   For loop1:=1 to maxpolys do
  1615.     For loop2:=1 to 4 do BEGIN
  1616.       Lines [loop1,loop2].x:=a [loop1,loop2,1]*8;
  1617.       Lines [loop1,loop2].y:=a [loop1,loop2,2]*8;
  1618.       Lines [loop1,loop2].z:=a [loop1,loop2,3]*8;
  1619.     END;
  1620.  
  1621.   SetUpPoints;
  1622.   LoadGFX;
  1623.  
  1624.   cls (vaddr,0);
  1625.   cls (vga,0);
  1626.   Xoff := 160;
  1627.   Yoff:=100;
  1628.   zoff:=-600;
  1629.  
  1630.   ytopclip:=101;
  1631.   ybotclip:=100;
  1632.   line (0,100,319,100,100,vga);
  1633.   delay (2000);
  1634.   for loop1:=1 to 25 do BEGIN
  1635.     RotatePoints (deg2,deg,deg2);
  1636.     SortPoints;
  1637.     DrawPoints;
  1638.     line (0,ytopclip,319,ytopclip,100,vaddr);
  1639.     line (0,ybotclip,319,ybotclip,100,vaddr);
  1640.     flip (vaddr,vga);
  1641.     cls (vaddr,0);
  1642.     deg:=(deg+5) mod 360;
  1643.     deg2:=(deg2+1) mod 360;
  1644.     ytopclip:=ytopclip-4;
  1645.     ybotclip:=ybotclip+4;
  1646.   END;
  1647.   Repeat
  1648.     if keypressed then ch:=upcase (Readkey);
  1649.     RotatePoints (deg2,deg,deg2);
  1650.     SortPoints;
  1651.     DrawPoints;
  1652.     line (0,0,319,0,100,vaddr);
  1653.     line (0,199,319,199,100,vaddr);
  1654.     flip (vaddr,vga);
  1655.     cls (vaddr,0);
  1656.     deg:=(deg+5) mod 360;
  1657.     deg2:=(deg2+3) mod 360;
  1658.   Until ch=#27;
  1659.   for loop1:=1 to 25 do BEGIN
  1660.     ytopclip:=ytopclip+4;
  1661.     ybotclip:=ybotclip-4;
  1662.     RotatePoints (deg2,deg,deg2);
  1663.     SortPoints;
  1664.     DrawPoints;
  1665.     line (0,ytopclip,319,ytopclip,100,vaddr);
  1666.     line (0,ybotclip,319,ybotclip,100,vaddr);
  1667.     flip (vaddr,vga);
  1668.     cls (vaddr,0);
  1669.     deg:=(deg+5) mod 360;
  1670.     deg2:=(deg2+1) mod 360;
  1671.   END;
  1672. END;
  1673.  
  1674.  
  1675. BEGIN
  1676.   clrscr;
  1677.   writeln ('Welcome to the twenty first trainer! This one is on texure mapping.');
  1678.   writeln;
  1679.   writeln ('Just sit bak and watch, it''s non interactive. Total reuse of Tut 20''s');
  1680.   writeln ('code, aside from the texure mapping procedure. Have fun!');
  1681.   writeln;
  1682.   writeln;
  1683.   write ('Hit any key to continue ...');
  1684.   readkey;
  1685.   SetUpVirtual;
  1686.   SetMCGA;
  1687.   MoveAround;
  1688.   SetText;
  1689.   ShutDown;
  1690.   Writeln ('All done. This concludes the twenty first sample program in the ASPHYXIA');
  1691.   Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
  1692.   Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS.I also occasinally');
  1693.   Writeln ('RSAProg, comp.lang.pascal and comp.sys.ibm.pc.demos. E-mail me at :');
  1694.   Writeln ('    denthor@goth.vironix.co.za');
  1695.   Writeln ('The numbers are available in the main text. You may also write to me at:');
  1696.   Writeln ('             Grant Smith');
  1697.   Writeln ('             P.O. Box 270');
  1698.   Writeln ('             Kloof');
  1699.   Writeln ('             3640');
  1700.   Writeln ('             Natal');
  1701.   Writeln ('             South Africa');
  1702.   Writeln ('I hope to hear from you soon!');
  1703.   Writeln; Writeln;
  1704.   Write   ('Hit any key to exit ...');
  1705.   readkey;
  1706. END.
  1707.